﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using SLMitsuControls;
using Visifire.Charts;
using Visifire.Commons;
using System.IO;
using System.Xml.Linq;

namespace SLWCFFlipBook
{

    public partial class Page : UserControl, IDataProvider
    {
        private bool _front = true;
        private Storyboard _sb = new Storyboard();
        private TimeSpan _tsLastFrame = new TimeSpan();
        private Chart BlackChart = new Chart();
        
        public Page(string PoshCharts)
        {            
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(Page_Loaded);
            this.btnRotate.Click += new RoutedEventHandler(btnRotate_Click);
            this.btnExecute.Click += new RoutedEventHandler(btnExecute_Click);
            this.btnFullScreen.Click += new RoutedEventHandler(btnFullScreen_Click);
            if (PoshCharts != "@PowerShellCode@")
            {
                CreateChart(PoshCharts);
            }
        }

        public List<Control> VisifirePages;
        
        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            
        }

        #region IDataProvider Members

        public object GetItem(int index)
        {
            return VisifirePages[index];
        }

        public int GetCount()
        {
            return VisifirePages.Count;
        }

        #endregion

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            book.AnimateToNextPage(300);
        
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            book.AnimateToPreviousPage(300);
        }

        void btnRotate_Click(object sender, RoutedEventArgs e)
        {
            if (_front)
            {
                _sb.Pause();
                _sb.AutoReverse = false;
                _sb.Begin();
                _front = false;
                txtPoshCode.Visibility = Visibility.Visible;
                txtPoshCode.IsEnabled = true;
                txtPoshCode.Focus();
            }
            else
            {
                _sb.Pause();
                _sb.AutoReverse = true;
                _sb.Seek(_tsLastFrame);
                _sb.Resume();

                _front = true;
            }
        }

        void btnExecute_Click(object sender, RoutedEventArgs e)
        {
            
            // Call the WebService
            PoshboardWCFRef.Service1Client webService = new SLWCFFlipBook.PoshboardWCFRef.Service1Client();
            webService.ExecutePowerShellCodeCompleted += new EventHandler<SLWCFFlipBook.PoshboardWCFRef.ExecutePowerShellCodeCompletedEventArgs>(webService_ExecutePowerShellCodeCompleted);
            string PowerShellCode =  txtPoshCode.Text.ToString(); 
            webService.ExecutePowerShellCodeAsync(PowerShellCode);

            if (_front)
            {
                //_sb.Pause();
                //_sb.AutoReverse = false;
                //_sb.Begin();
                //_front = false;
            }
            else
            {
                _sb.Pause();
                _sb.AutoReverse = true;
                _sb.Seek(_tsLastFrame);
                _sb.Resume();
                _front = true;
            }
        }

        void btnFullScreen_Click(object sender, RoutedEventArgs e)
        {
            //FullScreen Test (not working yet)
        System.Windows.Application.Current.Host.Content.IsFullScreen = true;        
        // Root.ScaleX = (Application.Current.Host.Content.ActualWidth / width);
        // Root.ScaleY = (Application.Current.Host.Content.ActualHeight / height);
        front.Width = Application.Current.Host.Content.ActualWidth;
        front.Height = Application.Current.Host.Content.ActualHeight;
        LayoutRoot.Width = Application.Current.Host.Content.ActualWidth;
        LayoutRoot.Height = Application.Current.Host.Content.ActualHeight;
        book.Width = Application.Current.Host.Content.ActualWidth * 0.90;
        book.Height = Application.Current.Host.Content.ActualHeight;
        }


        private double width;
        private double height;

        void Page_Loaded(object sender, RoutedEventArgs e)
        {
            TransformGroup transforms = new TransformGroup();
            ScaleTransform scale = new ScaleTransform();
            height = this.Height;
            width = this.Width;
            Application.Current.Host.Content.Resized += new EventHandler(Resized);
            Application.Current.Host.Content.FullScreenChanged += new EventHandler(Resized); 

            transforms.Children.Add(scale);
            this.screens.RenderTransform = transforms;

            Storyboard sbForward = new Storyboard();
            AnimateFlip(_sb, scale, out _tsLastFrame);

            this.LayoutRoot.Resources.Add("Animation", _sb);
        }



        private void Resized(object sender, EventArgs e)
        {

            if (Application.Current.Host.Content.IsFullScreen)
            {

                //if is fullscreen then zoom

                //Root.ScaleX = (Application.Current.Host.Content.ActualWidth / width);

                //Root.ScaleY = (Application.Current.Host.Content.ActualHeight / height);

            }

            else
            {

                //exit fullscreen remove zoom

                //Root.ScaleX = 1;

                //Root.ScaleY = 1;

            }

        }


        void webService_ExecutePowerShellCodeCompleted(object sender, SLWCFFlipBook.PoshboardWCFRef.ExecutePowerShellCodeCompletedEventArgs e)
        {
            // Build the book when Execution of PowerShell script is done
            CreateChart(e.Result);
        }

        private void CreateChart(string chartsdata)
        {
            VisifirePages = new List<Control> { };
            if (chartsdata.Contains('§') != true)
            {
                TextBox myCover = new TextBox();
                myCover.Text = chartsdata;                
                myCover.VerticalAlignment = VerticalAlignment.Stretch;
                myCover.TextAlignment = TextAlignment.Center;
                myCover.TextWrapping = TextWrapping.Wrap;

                myCover.FontSize = 25;
                //myCover.Background = new ImageBrush { ImageSource = new BitmapImage(new Uri("powershell.jpg", UriKind.Relative)) };
                myCover.Background = new SolidColorBrush(Colors.Black);
                myCover.Foreground = new SolidColorBrush(Colors.White);
                myCover.OpacityMask = new SolidColorBrush(Colors.White);
                myCover.Opacity = 0.8;
                VisifirePages.Add(myCover);
                book.SetData(this);
            }
            else
            {
                VisifirePages = new List<Control> { };
                //Build Cover
                TextBox myCover = new TextBox();
                myCover.Text = "Your scripts\r\n";
                myCover.Text += "inside\r\n";
                myCover.Text += "Mitsu Flipbook Control\r\n";
                myCover.VerticalAlignment = VerticalAlignment.Stretch;
                myCover.TextAlignment = TextAlignment.Center;
                myCover.FontSize = 25;
                //myCover.Background = new ImageBrush { ImageSource = new BitmapImage(new Uri("powershell.jpg", UriKind.Relative)) };
                myCover.Background = new SolidColorBrush(Colors.Black);
                myCover.Foreground = new SolidColorBrush(Colors.White);
                myCover.OpacityMask = new SolidColorBrush(Colors.White);
                myCover.Opacity = 0.8;
                VisifirePages.Add(myCover);

                // Generate Charts
                string PoshCharts = chartsdata;
                foreach (string SingleChart in PoshCharts.Split('§'))
                {
                    if (SingleChart != "\r\n\r\n" && SingleChart != "")
                    {
                        // Create a new Visifire Chart
                        BlackChart = new Chart();
                        string strChartSetup = SingleChart.Split('£')[0];
                        string strChartSeriesType = SingleChart.Split('£')[1];
                        string strChartSeriesName = SingleChart.Split('£')[2];
                        string strChartDataName = SingleChart.Split('£')[3];
                        string strChartData = SingleChart.Split('£')[4];
                        int intNbrSeries = strChartSeriesType.Split('µ').Count() - 1;

                        BlackChart.Background = new SolidColorBrush(Colors.Black);
                        BlackChart.Width = 430;
                        BlackChart.Height = 420;
                        BlackChart.AnimationEnabled = false;
                        ////Add Title
                        Title title = new Title();

                        title.Text = strChartSetup.Split('µ')[0];
                        title.FontSize = 25.0;
                        BlackChart.Titles.Add(title);

                        if (strChartSetup.Split('µ')[1] != "")
                        {
                            Axis axisX = new Axis();
                            axisX.Title = strChartSetup.Split('µ')[1];
                            BlackChart.AxesX.Add(axisX);
                        }

                        if (strChartSetup.Split('µ')[2] != "")
                        {
                            Axis axisY = new Axis();
                            axisY.Title = strChartSetup.Split('µ')[2];
                            BlackChart.AxesY.Add(axisY);
                        }

                        for (int i = 0; i < intNbrSeries; i++)
                        {
                            DataSeries dataSeries = new DataSeries();
                            string SerieType = strChartSeriesType.Split('µ')[i];
                            switch (SerieType)
                            {
                                case "Area":
                                    dataSeries.RenderAs = RenderAs.Area;
                                    break;
                                case "Bar":
                                    dataSeries.RenderAs = RenderAs.Bar;
                                    break;
                                case "Bubble":
                                    dataSeries.RenderAs = RenderAs.Bubble;
                                    break;
                                case "Column":
                                    dataSeries.RenderAs = RenderAs.Column;
                                    break;
                                case "Doughnut":
                                    dataSeries.RenderAs = RenderAs.Doughnut;
                                    break;
                                case "Line":
                                    dataSeries.RenderAs = RenderAs.Line;
                                    break;
                                case "Pie":
                                    dataSeries.RenderAs = RenderAs.Pie;
                                    break;
                                case "Point":
                                    dataSeries.RenderAs = RenderAs.Point;
                                    break;
                                case "StackedArea":
                                    dataSeries.RenderAs = RenderAs.StackedArea;
                                    break;
                                case "StackedBar":
                                    dataSeries.RenderAs = RenderAs.StackedBar;
                                    break;
                                case "StackedColumn":
                                    dataSeries.RenderAs = RenderAs.StackedColumn;
                                    break;
                            }


                            dataSeries.Name = strChartSeriesName.Split('µ')[i];
                            dataSeries.LegendText = strChartSeriesName.Split('µ')[i];
                            int nbrData = strChartData.Split('µ').Count();

                            int l = 0;
                            if (intNbrSeries >= 2)
                            {
                                string strCurrentData = strChartData.Split('µ')[i];

                                foreach (string strDataPoint in strCurrentData.Split('¤'))
                                {
                                    if (strDataPoint != "")
                                    {
                                        DataPoint dataPoint;
                                        dataPoint = new DataPoint();
                                        dataPoint.YValue = Convert.ToDouble(strDataPoint);
                                        dataPoint.AxisXLabel = strChartDataName.Split('µ')[l];
                                        dataSeries.DataPoints.Add(dataPoint);
                                        l++;
                                    }
                                }
                                BlackChart.Series.Add(dataSeries);
                            }

                            if (intNbrSeries < 2)
                            {
                                for (int k = 0; k < nbrData; k++)
                                {
                                    string strCurrentData = strChartData.Split('µ')[k];
                                    foreach (string strDataPoint in strCurrentData.Split('¤'))
                                    {
                                        if (strDataPoint != "")
                                        {
                                            DataPoint dataPoint;
                                            dataPoint = new DataPoint();
                                            dataPoint.YValue = Convert.ToDouble(strDataPoint);
                                            dataPoint.AxisXLabel = strChartDataName.Split('µ')[k];
                                            dataSeries.DataPoints.Add(dataPoint);
                                        }
                                    }
                                }
                                BlackChart.Series.Add(dataSeries);

                            }
                        }
                        VisifirePages.Add(BlackChart);
                    }
                    book.SetData(this);
                }

                int j = 0;
                foreach (var b in VisifirePages)
                {
                    if (j % 2 == 0)
                        b.MouseLeftButtonDown += Button_Click;
                    else
                        b.MouseLeftButtonDown += Button_Click_1;
                    j++;
                }
            }
        }
        #region Animations
        private static KeySpline DefineKeySpline(double cp1X, double cp1Y, double cp2X, double cp2Y)
        {
            KeySpline ksStart = new KeySpline();
            ksStart.ControlPoint1 = new Point(cp1X, cp1Y);
            ksStart.ControlPoint2 = new Point(cp2X, cp2Y);
            return ksStart;
        }

        private TimeSpan AnimateFlip(Storyboard sb, ScaleTransform scale, out TimeSpan tsLastFrame)
        {
            double speed = 4;
            double flipRotation = 0;
            double flipped = 2;
            tsLastFrame = new TimeSpan();
            TimeSpan tsSideFlipped = new TimeSpan();

            int frames = 1;
            DoubleAnimationUsingKeyFrames daX = new DoubleAnimationUsingKeyFrames();
            tsLastFrame = new TimeSpan();
            while (flipRotation != flipped * 180)
            {
                flipRotation += speed;
                double flipRadian = flipRotation * (Math.PI / 180);
                double size = Math.Cos(flipRadian);
                double scalar = (1 / (1 / size));

                DiscreteDoubleKeyFrame ddkfX = new DiscreteDoubleKeyFrame();
                ddkfX.Value = (size * scalar);

                tsLastFrame = TimeSpan.FromMilliseconds(frames * 7);

                //the first time we flip to negative capture the tsLastFrame so we know when we will need to
                //visualize the flip side
                flipped = (size < 0) ? +1 : +0;
                if (flipped == 1 && tsSideFlipped.Ticks == 0)
                {
                    tsSideFlipped = tsLastFrame;
                }

                ddkfX.KeyTime = KeyTime.FromTimeSpan(tsLastFrame);

                //add the DiscreteDoubleKeyFrame to the DoubleAnimationUsingKeyFrames
                daX.KeyFrames.Add(ddkfX);

                flipRotation %= 360;
                frames++;
            }

            Storyboard.SetTarget(daX, scale);
            Storyboard.SetTargetProperty(daX, new PropertyPath("(ScaleX)"));
            sb.Children.Add(daX);

            VisualizeSide(sb, tsSideFlipped, 0, TimeSpan.FromMilliseconds((tsSideFlipped.Milliseconds + 100)), back.Opacity, this.back);
            VisualizeSide(sb, TimeSpan.FromMilliseconds((tsSideFlipped.Milliseconds - 100)), front.Opacity, tsSideFlipped, 0, this.front);
            back.Opacity = 0;
            return tsLastFrame;
        }

        private void VisualizeSide(Storyboard sb, TimeSpan tsStart, double opacityStart, TimeSpan tsEnd, double opacityEnd, UIElement side)
        {
            DoubleAnimationUsingKeyFrames daOpacity = new DoubleAnimationUsingKeyFrames();
            SplineDoubleKeyFrame sdkfStart = new SplineDoubleKeyFrame();
            sdkfStart.Value = opacityStart;
            sdkfStart.KeyTime = tsStart;
            sdkfStart.KeySpline = DefineKeySpline(0, 0, 1, 1);
            daOpacity.KeyFrames.Add(sdkfStart);

            SplineDoubleKeyFrame sdkfEnd = new SplineDoubleKeyFrame();
            sdkfEnd.Value = opacityEnd;
            sdkfEnd.KeyTime = tsEnd;
            sdkfEnd.KeySpline = DefineKeySpline(0, 0, 1, 1);
            daOpacity.KeyFrames.Add(sdkfEnd);

            Storyboard.SetTarget(daOpacity, side);
            Storyboard.SetTargetProperty(daOpacity, new PropertyPath("(UIElement.Opacity)"));

            sb.Children.Add(daOpacity);            
        }
    }
        #endregion
}